package cc.rengu.igas.channel.upac.core.service.trans;

import cc.rengu.igas.channel.upac.common.constant.UpacConfigConstant;
import cc.rengu.igas.channel.upac.common.constant.UpacParamConstant;
import cc.rengu.igas.channel.upac.common.constant.UpacTreeNodeConstant;
import cc.rengu.igas.channel.upac.common.util.UpacSecurityUtil;
import cc.rengu.igas.channel.upac.core.model.ChnlBizResponse;
import cc.rengu.igas.channel.upac.core.service.base.NoticeService;
import cc.rengu.igas.channel.upac.facade.request.RefundResultNoticeRequest;
import cc.rengu.igas.channel.upac.facade.response.RefundResultNoticeResponse;
import cc.rengu.igas.share.facade.request.UpacRefundResultNoticeRequest;
import cc.rengu.igas.share.facade.response.UpacRefundResultNoticeResponse;
import cc.rengu.igas.share.facade.result.Result;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.CertInfoMapper;
import cc.rengu.oltp.service.common.dao.DstChannelCfgMapper;
import cc.rengu.oltp.service.common.dao.SecPlanInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.CertInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.DstChannelCfgMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.SecPlanInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.CertInfo;
import cc.rengu.oltp.service.common.entity.DstChannelCfg;
import cc.rengu.oltp.service.common.entity.SecPlanInfo;
import cc.rengu.oltp.service.common.entity.SysParam;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.realize.DubboService;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 银联全渠道退款结果通知服务
 * Created by fyp on 2020/5/6.
 */
public class RefundResultNoticeService extends NoticeService {

    @Override
    protected Object beforeBizProcess() throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        RefundResultNoticeRequest refundResultNoticeRequest = new RefundResultNoticeRequest();
        ConvertUtil.convertOutput(refundResultNoticeRequest);
        String instId = refundResultNoticeRequest.getHeader().getInstId();
        CertInfo encryptCertInfo = null;
        /* 若有上送卡号，先解密卡号 */
        if (!StringUtil.isEmptyOrNull(refundResultNoticeRequest.getPayAcctNo())) {
            SysParamService sysParamService = new SysParamServiceImpl();
            /* 获取银联全渠道报文字体集类型 */
            SysParam sysParam = sysParamService.getSysParamInfo(instId, UpacConfigConstant.UPAC_CONF_NODE, UpacConfigConstant.UPAC_ENCODING);
            if (sysParam != null) {
                xmlTreeUtil.setXmlTreeStringValue(UpacTreeNodeConstant.version, sysParam.getParamValue());
            }
            String encoding = (null == sysParam) ? UpacParamConstant.UTF_8_ENCODING : sysParam.getParamValue();
            /* 获取银联全渠道卡号加密方式 */
            sysParam = sysParamService.getSysParamInfo(instId, UpacConfigConstant.UPAC_CONF_NODE, UpacConfigConstant.UPAC_ACCT_ENC);
            String acctNoEncType = null == sysParam ? AppParamConstant.NO : sysParam.getParamValue();
            if (AppParamConstant.YES.equals(acctNoEncType)) {
                /* 获取敏感信息解密证书,查询通道配置表 */
                DstChannelCfgMapper dstChannelCfgMapper = new DstChannelCfgMapperImpl();
                List<DstChannelCfg> dstChannelCfgList = dstChannelCfgMapper.selectDstChannelCfgBydstChannelId(instId, ChannelEnum.UPAC.getChannelType());
                if (dstChannelCfgList == null || dstChannelCfgList.isEmpty()) {
                    throw new BizException(OltpRpcdEnum.CHANNEL_DISABLED);
                }
                dstChannelCfgList = dstChannelCfgList.stream().filter(item -> item.getProviderMchntNo().equals(refundResultNoticeRequest.getUpacMchntNo())).collect(Collectors.toList());
                if (dstChannelCfgList.isEmpty()) {
                    throw new BizException(OltpRpcdEnum.CHANNEL_DISABLED);
                }
                xmlTreeUtil.setXmlTreeObjectValue(UpacTreeNodeConstant.DST_CHANNEL_CFG, dstChannelCfgList.get(0));

                /* 根据通道安全计划获取安全计划 */
                SecPlanInfoMapper secPlanInfoMapper = new SecPlanInfoMapperImpl();
                List<SecPlanInfo> secPlanInfoList = secPlanInfoMapper.selectSecPlanInfoBySecPlanId(instId, dstChannelCfgList.get(0).getSecPlanId());
                if (null != secPlanInfoList && !secPlanInfoList.isEmpty()) {
                    xmlTreeUtil.setXmlTreeStringValue(UpacTreeNodeConstant.SEC_PLAN_INFO_LIST, JSON.toJSONString(secPlanInfoList));
                    /* 解密证书 */
                    Optional<SecPlanInfo> secPlanInfoOpt = secPlanInfoList.stream().filter(item -> item.getSecPlanType().equals(UpacParamConstant.DECRYPT_CERT_TYPE)).findFirst();
                    if (secPlanInfoOpt.isPresent()) {
                        CertInfoMapper certInfoMapper = new CertInfoMapperImpl();
                        encryptCertInfo = certInfoMapper.selectCertInfoByPrimaryKey(secPlanInfoOpt.get().getInstId() + secPlanInfoOpt.get().getSecPlanId() + secPlanInfoOpt.get().getSecPlanType());
                    }
                }
                if (encryptCertInfo == null) {
                    rglog.error("获取商户<{}>的解密证书失败", refundResultNoticeRequest.getUpacMchntNo());
                    throw new BizException(OltpRpcdEnum.CHANNEL_DISABLED);
                }
                xmlTreeUtil.setXmlTreeObjectValue("encryptCertInfo", encryptCertInfo);
                String acctNo = UpacSecurityUtil.decryptData(refundResultNoticeRequest.getPayAcctNo(), encryptCertInfo.getCertValue(), encoding);
                rglog.debug("acctNo=[{}]", acctNo);
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.PAYER_ACCT_INFO, acctNo);
                refundResultNoticeRequest.setPayAcctNo(acctNo);
            }
        }
        return refundResultNoticeRequest;
    }

    @Override
    protected ChnlBizResponse callBizService(Object request) throws Exception {
        RefundResultNoticeRequest refundResultNoticeRequest = (RefundResultNoticeRequest) request;
        RefundResultNoticeResponse refundResultNoticeResponse = new RefundResultNoticeResponse();

        /* 调用Share模块中的银联二维码业务公共处理服务 */
        UpacRefundResultNoticeRequest upacRefundResultNoticeRequest = new UpacRefundResultNoticeRequest();
        BeanUtil.beanCopy(refundResultNoticeRequest, upacRefundResultNoticeRequest);
        upacRefundResultNoticeRequest.getHeader().setTxnNum("T00SH008");
        upacRefundResultNoticeRequest.getHeader().setTraceNo(ChannelEnum.UPAC.getChannelType() + DateUtil.getCurrentDateTime("yyyyMMddHHmmssSSS") + RandomUtil.randomNumStr(10));
        DubboService dubboService = new DubboServiceImpl();
        Result<UpacRefundResultNoticeResponse> callResult = (Result<UpacRefundResultNoticeResponse>) dubboService.callDubboService("upacUnifiedService", "refundResultNotice", upacRefundResultNoticeRequest);
        if (null != callResult) {
            UpacRefundResultNoticeResponse upacRefundResultNoticeResponse = callResult.getResult();
            BeanUtil.beanCopy(upacRefundResultNoticeResponse, refundResultNoticeResponse);
        }

        /* 组装应答报文 */
        ChnlBizResponse chnlBizResponse = new ChnlBizResponse();
        chnlBizResponse.setResult(refundResultNoticeResponse);
        return chnlBizResponse;
    }

    @Override
    protected void afterBizProcess(ChnlBizResponse response) throws Exception {
        RefundResultNoticeResponse refundResultNoticeResponse = (RefundResultNoticeResponse) response.getResult();
        ConvertUtil.convertInput(refundResultNoticeResponse);
    }
}
